package com.thoughtworks.recruit.test.jgraph.graph;

import com.thoughtworks.recruit.test.jgraph.interfaces.DiGraph;
import com.thoughtworks.recruit.test.jgraph.interfaces.EdgeFactory;
import com.thoughtworks.recruit.test.jgraph.graph.builder.*;

/**
 * A directed weighted graph. A directed weighted graph is a non-simple directed graph in which
 * multiple edges between any two vertices are <i>not</i> permitted, but loops are. The graph has
 * weights on its edges.
 *
 * @param <V> the graph vertex type
 * @param <E> the graph edge type
 *
 * @see DefaultDiGraph
 */
public class DefaultDiWeightedGraph<V, E>
    extends DefaultDiGraph<V, E>
    implements DiGraph.WeightedGraph<V, E>
{
    private static final long serialVersionUID = 1L;

    /**
     * Creates a new directed weighted graph.
     *
     * @param edgeClass class on which to base factory for edges
     */
    public DefaultDiWeightedGraph(Class<? extends E> edgeClass)
    {
        this(new BasedEdgeFactory<>(edgeClass));
    }

    /**
     * Creates a new directed weighted graph with the specified edge factory.
     *
     * @param ef the edge factory of the new graph.
     */
    public DefaultDiWeightedGraph(EdgeFactory<V, E> ef)
    {
        super(ef);
    }

    /**
     * Create a builder for this kind of graph.
     * 
     * @param edgeClass class on which to base factory for edges
     * @param <V> the graph vertex type
     * @param <E> the graph edge type
     * @return a builder for this kind of graph
     */
    public static <V, E> DiWeightedGraphBuilderBase<V, E,
            ? extends DefaultDiWeightedGraph<V, E>, ?> builder(Class<? extends E> edgeClass)
    {
        return new DiWeightedGraphBuilder<>(new DefaultDiWeightedGraph<>(edgeClass));
    }

    /**
     * Create a builder for this kind of graph.
     * 
     * @param ef the edge factory of the new graph
     * @param <V> the graph vertex type
     * @param <E> the graph edge type
     * @return a builder for this kind of graph
     */
    public static <V, E> DiWeightedGraphBuilderBase<V, E,
            ? extends DefaultDiWeightedGraph<V, E>, ?> builder(EdgeFactory<V, E> ef)
    {
        return new DiWeightedGraphBuilder<>(new DefaultDiWeightedGraph<>(ef));
    }
}